<?php

declare (strict_types = 1);

namespace App\Endpoint\Console;

use Cycle\Database\DatabaseManager;
use Spiral\Boot\DirectoriesInterface;
use Spiral\Console\Attribute\Argument;
use Spiral\Console\Attribute\AsCommand;
use Spiral\Console\Command;

#[AsCommand(name: 'gene:code')]
final class GeneCodeCommand extends Command
{
    #[Argument(name: 'database', description: 'The db name')]
    private string $database;

    #[Argument(name: 'table', description: 'The table name')]
    private string $table;

    #[Argument(name: 'group', description: 'code group')]
    private ?string $group;

    private static $dir;

    private $directories;

    private DatabaseManager $db;

    public function __construct(DatabaseManager $db)
    {
        parent::__construct();
        $this->db = $db;
    }

    public function __invoke(DirectoriesInterface $directories)
    {
        $dbConn            = $this->db->database();
        $this->directories = $directories;

        $table          = $this->table;
        $group          = $this->group;
        $groupNamespace = '';
        // dump(directory('root'));
        // dump(['a' => 'b']);
        // dump($this->directories->get('root'));

        self::$dir = $this->directories->get('root') . '/code';
        self::geneDir(self::$dir);

        if ($group) {
            $groupNamespace = "\\" . ucfirst($group);
            $group          = '/' . ucfirst($group);
        }

        /**
         * COLUMN_NAME AS '列名',
        DATA_TYPE AS '数据类型',
        CHARACTER_MAXIMUM_LENGTH AS '长度',
        IS_NULLABLE AS '是否为空',
        COLUMN_DEFAULT AS '默认值',
        COLUMN_COMMENT AS '备注'
         */
        $tableSql  = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '{$this->database}' AND TABLE_NAME = '{$table}'";
        $tableInfo = $dbConn->query($tableSql)->fetchAll();
        self::geneModelText($table, $tableInfo, $group, $groupNamespace);
        self::geneControllerText($table, $tableInfo, $group, $groupNamespace);
        self::geneServiceText($table, $tableInfo, $group, $groupNamespace);
        self::geneRoute($table, $tableInfo, $group, $groupNamespace);
    }

    public static function geneModelText($tableName, $tableInfo, $group, $groupNamespace)
    {
        $tableCamelCase = self::underscoreToCamelCase($tableName);
        $jsonColumn     = collect($tableInfo)->where('DATA_TYPE', 'json');
        $case           = '';
        foreach ($jsonColumn as $item) {
            $case .= "\n        '{$item['COLUMN_NAME']}' => 'json',";
        }
        $text = <<<EOT
<?php

namespace App\Model{$groupNamespace};

use Illuminate\Database\Eloquent\Model;

class {$tableCamelCase} extends Model
{
    protected \$connection = '';
    protected \$table = '{$tableName}';
    protected \$guarded = [];
    protected \$casts = [{$case}
    ];
    // public \$timestamps = false;
}
EOT;

        $filename = self::$dir . "/{$tableCamelCase}.php";
        self::fileGene($filename, $text);
        echo "model文件生成成功: {$filename}\n";
    }

    public static function geneControllerText($tableName, $tableInfo, $group, $groupNamespace)
    {
        $tableCamelCase = self::underscoreToCamelCase($tableName);
        $tableInfo      = collect($tableInfo);

        $fieldStr    = "";
        $fieldArrStr = "";
        foreach ($tableInfo as $key => $item) {
            if (in_array($item['COLUMN_NAME'], ['created_at', 'updated_at', 'add_time', 'update_time'])) {
                continue;
            }
            $fieldArrStr .= "\n                '{$item['COLUMN_NAME']}' => '{$item['COLUMN_COMMENT']}',";

            if (in_array($item['COLUMN_NAME'], ['id'])) {
                continue;
            }
            $fieldStr .= "'{$item['COLUMN_NAME']}', " . ($key % 5 == 0 ? '\n' : '');
        }

        $text = <<<EOT
<?php
namespace App\Http\Controllers{$groupNamespace};

use App\Exports\Export;
use App\Http\Controllers\Controller;
use App\Services{$groupNamespace}\\{$tableCamelCase}Service;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Excel;

class {$tableCamelCase}Controller extends Controller
{
    /**
     * 列表
     */
    public function index(Request \$request)
    {
        \$params = \$request->only([
            'page', 'pageSize', {$fieldStr}'export',
        ]);
        if (! empty(\$params['export'])) {
            \$params['page'] = 1;
            \$params['pageSize'] = 100000;
        }
        \$list = {$tableCamelCase}Service::lists(\$params);
        if (isset(\$params['export']) && \$params['export'] == 1) {
            \$headings = [{$fieldArrStr}
            ];
            header("access-control-expose-headers: Authorization, Content-Disposition");
            \$export = new Export(\$list['data'], \$headings);
            return \$export->download("功能名_" . date('Y-m-d') . ".xlsx", Excel::XLSX);

        }
        return \$this->ret(0, '', \$list);
    }

    public function store(Request \$request)
    {
        \$params = \$request->only([
            'id', {$fieldStr}
        ]);
        \$res = {$tableCamelCase}Service::store(\$params);
        return \$this->ret(0, '', [
            'res' => \$res,
        ]);
    }

}
EOT;

        $filename = self::$dir . "/{$tableCamelCase}Controller.php";
        self::fileGene($filename, $text);
        echo "controller文件生成成功: {$filename}\n";
    }

    public static function geneServiceText($tableName, $tableInfo, $group, $groupNamespace)
    {
        $tableCamelCase = self::underscoreToCamelCase($tableName);
        $tableInfo      = collect($tableInfo);

        $fieldStr    = "";
        $whereArrStr = "";
        foreach ($tableInfo as $key => $item) {
            if (in_array($item['COLUMN_NAME'], ['created_at', 'updated_at', 'add_time', 'update_time'])) {
                continue;
            }
            if ($item['COLUMN_NAME'] == 'name') {
                $whereArrStr .= (empty($whereArrStr) ? '' : '->') . "when(\$arg = Arr::get(\$params, 'name'), function (\$query) use (\$arg) {
            \$query->where('name', 'like', '%' . \$arg . '%');
        })";
            } else {
                $whereArrStr .= (empty($whereArrStr) ? '' : '->') . "when(\$arg = Arr::get(\$params, '{$item['COLUMN_NAME']}'), function (\$query) use (\$arg) {
            \$query->where('{$item['COLUMN_NAME']}', \$arg);
        })";
            }

            if (in_array($item['COLUMN_NAME'], ['id'])) {
                continue;
            }
            $fieldStr .= "'{$item['COLUMN_NAME']}', " . ($key % 5 == 0 ? '\n' : '');
        }

        $text = <<<EOT
<?php

namespace App\Services;

use App\Components\Library;
use App\Exceptions\ApiException;
use App\Model{$groupNamespace}\{$tableCamelCase};
//use App\Model\User\SystemUserModel;
use Illuminate\Support\Arr;

class {$tableCamelCase}Service extends BaseService
{
    public static function lists(array \$params)
    {
        \$page = Arr::get(\$params, 'page', 1);
        \$limit = Arr::get(\$params, 'pagesize', 10);
        \$order_field = Arr::get(\$params, 'order_field', 'id');
        \$order_type = Arr::get(\$params, 'order_type', 'desc');
        \$result = {$tableCamelCase}::{$whereArrStr}->orderBy(\$order_field, \$order_type)
            ->paginate(\$limit, ['*'], 'page', \$page)->toArray();

        foreach (\$result['data'] as &\$item) {
            //\$item['create_system_user'] = '';
            //if (!empty(\$item['create_system_uid'])) {
            //    \$system_user = SystemUserModel::find(\$item['create_system_uid']);
            //    \$item['create_system_user'] = \$system_user->user_name ?? '';
            //}
        }
        return Library::pageFilter(\$result);
    }

    public static function store(\$params)
    {
        if (!empty(\$params['name'])) {
            \$info = {$tableCamelCase}::where('name', \$params['name']);
            if (!empty(\$params['id'])) {
                \$info->where('id', '!=', \$params['id']);
            }
            if (\$info->exists()) {
                throw new ApiException('客户名已存在');
            }
        }
        if (!empty(\$params['id'])) {
            \$model = {$tableCamelCase}::findOrFail(\$params['id']);
        } else {
            \$model = new {$tableCamelCase}();
        }
        \$model->fill(\$params)->save();
        return \$model->id;
    }
}
EOT;

        $filename = self::$dir . "/{$tableCamelCase}Service.php";
        self::fileGene($filename, $text);
        echo "service文件生成成功: {$filename}\n";
    }

    public static function geneRoute($tableCamelCase)
    {
        $tableCamelCase2 = lcfirst($tableCamelCase);
        $text            = <<<EOT
\n    Route::post('{$tableCamelCase2}/list', [{$tableCamelCase}Controller::class, '{$tableCamelCase2}List']);
    Route::post('{$tableCamelCase2}', [{$tableCamelCase}Controller::class, '{$tableCamelCase2}Store']);
EOT;

        $filename = self::$dir . "/route.php";
        self::fileGeneAfter($filename, $text);
        echo "controller文件生成成功: {$filename}\n";
    }

    public static function underscoreToCamelCase($string)
    {
        // 将字符串以下划线分割为数组
        $parts = explode('_', $string);

        // 将每个部分的首字母大写
        $camelCaseString = '';
        foreach ($parts as $part) {
            $camelCaseString .= ucfirst($part);
        }

        return $camelCaseString;
    }

    public static function fileGene($filename, $content)
    {
        $file = fopen($filename, "w");
        fwrite($file, $content);
        fclose($file);
    }

    public static function fileGeneAfter($filename, $content)
    {
        $file = fopen($filename, "a");
        fwrite($file, $content);
        fclose($file);
    }

    public static function geneDir($dirname)
    {
        // $dir = dirname($dirname);
        if (! is_dir($dirname)) {
            mkdir($dirname, 0777, true);
        }
    }
}
